//
//  CLComponentXMLParser.m
//  ComponentLinkDemo
//
//  Created by newworld on 2017/3/2.
//  Copyright © 2017年 zhenby. All rights reserved.
//

#import "CLComponentXMLParser.h"
#import <KissXML/KissXML.h>
#import "CLPComponent.h"
#import "CLComponentRuntimeUtils.h"

#import <objc/runtime.h>

typedef id<CLPComponent> ComponentT;

static  NSString * kClass       = @"class";
static  NSString * kLayout      = @"layout";
static  NSString * kAction      = @"action";
static  NSString * kID          = @"id";
static  NSString * kProperty    = @"property";


@implementation CLComponentXMLParser


#pragma mark - Public Method

+ (id<CLPComponent>)componentWithXMLFile:(NSString *)path
{
    NSData *fileData = [NSData dataWithContentsOfFile:path];
    DDXMLDocument *xmlDoc = [[DDXMLDocument alloc] initWithData:fileData options:0 error:nil];
    return [self parseAComponentWithElement:xmlDoc.rootElement];
}

+ (id<CLPComponent>)componentWithXMLData:(NSString *)xmlData
{
    return nil;
}



+ (id<CLPComponent>)parseAComponentWithElement:(DDXMLElement *)element
{
    id<CLPComponent> component = nil;
    
    if (!element) {
        return component;
    }
    
    NSString *className = element.name;
    Class componentClass = objc_getClass(className.UTF8String);
    if (componentClass && [componentClass conformsToProtocol:@protocol(CLPComponent)]) {
        component = [[componentClass alloc] init];
        
        // 解析属性
        NSString *componentID = [[element attributeForName:kID] stringValue];
        NSString *layoutStr = [[element attributeForName:kLayout] stringValue];
        NSString *propertyStr = [[element attributeForName:kProperty] stringValue];
        NSString *actionStr = [[element attributeForName:kAction] stringValue];
        
        if (componentID) {
            [component setComponentID:componentID];
        }
        
        // layout 中当前定义的格式为 k1:v1,k2:v2 的格式
        if (layoutStr) {
            [self parseLayout:layoutStr ToComponent:component];
        }
        
        if (propertyStr) {
            [self parseProperty:propertyStr ToComponent:component];
        }
        
        if(actionStr){
            [self parseAction:actionStr ToComponent:component];
        }
        
        // 递归解析子组件
        for (DDXMLNode *childNode in element.children) {
            if ([childNode isKindOfClass:[DDXMLElement class]]) {
                id<CLPComponent> subcomponent = [self parseAComponentWithElement:(DDXMLElement *)childNode];
                if (subcomponent) {
                    [component addSubcomponent:subcomponent];
                }
            }
        }
    }
    
    return component;
}


#pragma mark - parse detail

+ (void) parseLayout:(NSString *)layoutStr ToComponent:(ComponentT)component
{
    NSArray *layouts = [layoutStr componentsSeparatedByString:@","];
    for (NSString *aLayoutStr in layouts) {
        NSArray *aLayout = [aLayoutStr componentsSeparatedByString:@":"];
        if ([aLayout count] == 2) {
            NSString *key = [aLayout[0] stringByTrimmingCharactersInSet:
                             [NSCharacterSet whitespaceAndNewlineCharacterSet]];
            NSString *value = [aLayout[1] stringByTrimmingCharactersInSet:
                               [NSCharacterSet whitespaceAndNewlineCharacterSet]];
            
            if ([component conformsToProtocol:@protocol(CLPViewComponent)]) {
                CLLayout *layout = [((id<CLPViewComponent>)component).layoutDesc layoutThatFitsInterfaceOrientation:UIInterfaceOrientationPortrait];
                [self setLayoutWithKey:key value:value inLayout:layout];
            }
        }
    }
}

+ (void) parseProperty:(NSString *)propertyStr ToComponent:(ComponentT)component
{
    // 使用 KVC 设置属性
    /*
        example: uicolor ,url
     */
    NSArray *properties = [propertyStr componentsSeparatedByString:@","];
    for (NSString *aPropertyStr in properties) {
        NSArray *aProperty = [aPropertyStr componentsSeparatedByString:@":"];
        if ([aProperty count] == 2) {
            NSString *key = [aProperty[0] stringByTrimmingCharactersInSet:
                             [NSCharacterSet whitespaceAndNewlineCharacterSet]];
            NSString *value = [aProperty[1] stringByTrimmingCharactersInSet:
                               [NSCharacterSet whitespaceAndNewlineCharacterSet]];
            id valueObject = value;
            
            if (key && [((NSObject *)component) validateValue:&valueObject forKeyPath:key error:nil]) {
                [((NSObject *)component) setValue:value forKeyPath:key];
            }
        }
    }

}

+ (void) parseAction:(NSString *)action ToComponent:(ComponentT)component
{
    /*
     uri:
     event
     */

    
}

+ (void)setLayoutWithKey:(NSString *)key value:(NSString *)value inLayout:(CLLayout *)layout
{
    key = [key lowercaseString];
    if ([key isEqualToString:@"width"]) {
        layout.width = CLDimensionMake(value);
    } else if ([key isEqualToString:@"height"]) {
        layout.height = CLDimensionMake(value);
    } else if ([key isEqualToString:@"flex-direction"]) {
        if ([value isEqualToString:@"row"]) {
            layout.flexDirection = CLFlexDirectionHorizontal;
        } else if ([value isEqualToString:@"row-reverse"]) {
            // TODO
        } else if ([value isEqualToString:@"column"]) {
            layout.flexDirection = CLFlexDirectionVertical;
        } else if ([value isEqualToString:@"column-reverse"]) {
            // TODO
        }
    } else if ([key isEqualToString:@"flex-wrap"]) {
        if ([value isEqualToString:@"nowrap"]) {
            layout.flexWrap = CLFlexWrapNoWrap;
        } else if ([value isEqualToString:@"wrap"]) {
            layout.flexWrap = CLFlexWrapWrap;
        }
    } else if ([key isEqualToString:@"flex-flow"]) {
        // TODO
    } else if ([key isEqualToString:@"justify-content"]) {
        if ([value isEqualToString:@"flex-start"]) {
            layout.justifyConent = CLFlexJustifyContentStart;
        } else if ([value isEqualToString:@"flex-end"]) {
            layout.justifyConent = CLFlexJustifyContentEnd;
        } else if ([value isEqualToString:@"center"]) {
            layout.justifyConent = CLFlexJustifyContentCenter;
        } else if ([value isEqualToString:@"space-between"]) {
            layout.justifyConent = CLFlexJustifyContentSpaceBetween;
        } else if ([value isEqualToString:@"space-around"]) {
            layout.justifyConent = CLFlexJustifyContentSpaceAround;
        }
    } else if ([key isEqualToString:@"align-items"]) {
        if ([value isEqualToString:@"stretch"]) {
            layout.alignItems = CLFlexAlignItemsStretch;
        } else if ([value isEqualToString:@"flex-start"]) {
            layout.alignItems = CLFlexAlignItemsStart;
        } else if ([value isEqualToString:@"flex-end"]) {
            layout.alignItems = CLFlexAlignItemsEnd;
        } else if ([value isEqualToString:@"center"]) {
            layout.alignItems = CLFlexAlignItemsCenter;
        } else if ([value isEqualToString:@"baseline"]) {
            layout.alignItems = CLFlexAlignItemsBaselineFirst;
        }
    } else if ([key isEqualToString:@"align-content"]) {
        if ([value isEqualToString:@"flex-start"]) {
            layout.alignContent = CLFlexAlignContentStart;
        } else if ([value isEqualToString:@"flex-end"]) {
            layout.alignContent = CLFlexAlignContentEnd;
        } else if ([value isEqualToString:@"center"]) {
            layout.alignContent = CLFlexAlignContentCenter;
        } else if ([value isEqualToString:@"space-between"]) {
            layout.alignContent = CLFlexAlignContentSpaceBetween;
        } else if ([value isEqualToString:@"space-around"]) {
            layout.alignContent = CLFlexAlignContentSpaceAround;
        }
    } else if ([key isEqualToString:@"flex-grow"]) {
        layout.flexGrow = value.floatValue;
    } else if ([key isEqualToString:@"flex-shrink"]) {
        layout.flexShrink = value.floatValue;
    } else if ([key isEqualToString:@"flex-basis"]) {
        layout.flexBasis = CLDimensionMake(value);
    } else if ([key isEqualToString:@"align-self"]) {
        if ([value isEqualToString:@"auto"]) {
            layout.alignSelf = CLFlexAlignSelfAuto;
        } else if ([value isEqualToString:@"flex-end"]) {
            layout.alignSelf = CLFlexAlignSelfStart;
        } else if ([value isEqualToString:@"flex-end"]) {
            layout.alignSelf = CLFlexAlignSelfEnd;
        } else if ([value isEqualToString:@"center"]) {
            layout.alignSelf = CLFlexAlignSelfCenter;
        } else if ([value isEqualToString:@"baseline"]) {
            // TODO
        } else if ([value isEqualToString:@"stretch"]) {
            layout.alignSelf = CLFlexAlignSelfStretch;
        }
    } else if ([key isEqualToString:@"top"]) {
        layout.top = value.floatValue;
    } else if ([key isEqualToString:@"left"]) {
        layout.left = value.floatValue;
    } else if ([key isEqualToString:@"right"]) {
        layout.right = value.floatValue;
    } else if ([key isEqualToString:@"bottom"]) {
        layout.bottom = value.floatValue;
    } else if ([key isEqualToString:@"margin-top"]) {
        layout.marginTop = value.floatValue;
    } else if ([key isEqualToString:@"margin-left"]) {
        layout.marginLeft = value.floatValue;
    } else if ([key isEqualToString:@"margin-right"]) {
        layout.marginRight = value.floatValue;
    } else if ([key isEqualToString:@"margin-bottom"]) {
        layout.marginBottom = value.floatValue;
    } else if ([key isEqualToString:@"margin"]) {
        layout.marginTop = value.floatValue;
        layout.marginLeft = value.floatValue;
        layout.marginRight = value.floatValue;
        layout.marginBottom = value.floatValue;
    } else if ([key isEqualToString:@"ratio"]) {
        layout.ratio = value.floatValue;
    }
}

@end
